Cross-site request forgery (CSRF, sometimes pronounced “sea surf” and not to be confused with cross-site scripting) is a simple yet invasive malicious exploit of a website. It involves a cyberattacker adding a button or link to a suspicious website that makes a request to another site you’re authenticated on. For example, a user is logged into their online banking platform which has poor security, and by clicking a “download” button on an untrusted site, it maliciously initiates a money transfer request on their behalf through their current online banking session. Compromised sites can reveal information or perform actions as an authorized user without your explicit permission.
CSRF attack prevention
Fortunately, CSRF attacks can be prevented. Let’s look at some of the most efficient ways to safeguard your website.
Being RESTful
Representational state transfer (REST) is a set of principles that assigns a type of activity (view, create, delete, update a resource) for each HTTP verb (GET, POST, PATCH, PUT, DELETE). Following a RESTful design will ensure that your code is clean and can scale. It also has the added benefit of reducing vulnerabilities.
A key design principle that protects you from CSRF attacks is using GET requests for only view or read-only actions. These types of requests should not transform data and must only display recorded data. This limits the number of requests that are vulnerable to CSRF attacks.
Anti-forgery tokens
Your website will also need to use POST, PUT, PATCH and DELETE requests. To safeguard these endpoints, you can introduce an anti-forgery token in every request that uniquely identifies safe origin sites.
Every response rendered by the server will contain the anti-forgery token which is then written out to a hidden HTML field. This token is used by the client side to authenticate requests sent to the server. Now, the server knows the request is from a safe origin.
Most modern web frameworks include anti-forgery token management, out-of-the-box. For example, Ruby on Rails has a method called “protect_from_forgery” that authenticates requests on the server side. It also manages token generation and rendering out to HTML elements.
Set cookies with the SameSite Attribute
Cookies are a way to add persistent state to websites. This is usually used to authorize users, store session data, and more. However, it’s also an easy way to expose vulnerabilities. To address this, cookies contain a number of attributes that govern their behavior.
A commonly used attribute is Max-Age. The Chrome team recently introduced the SameSite attribute (now available across most major browsers). It is exceptionally useful in thwarting CSRF attacks.
The SameSite attribute allows you to declare if your cookie should be restricted to a first-party or same-site context. It gives you greater control over how much a client can access server-side code.
Setting a Same-Site attribute to a cookie is quite simple:
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
Set-Cookie: CookieName=CookieValue; SameSite=Strict;
If the value is set to Strict, it means that any request originating from a third-party site to your site will have all cookies removed by the browser. It is the most secure setting and helps in preventing untrusted authorized requests from being rendered.
Setting the value to Lax does not remove the cookies for any GET requests. This provides a seamless experience for your user when they follow links from other sites to your site. Otherwise, your user would have to reauthenticate to gain access.
Enabling CORS protection
Cross-origin resource sharing (CORS) adds flexibility to the same-origin policy (SOP). It allows for a controlled access to requests originating outside of a given domain. It is generally used when you need to serve API requests.
Having said this, relaxing the SOP policy does open up your site to cross-domain based attacks. Fortunately, this can be prevented by having a good control over your CORS policy.
The request headers related to the policy are:
- Origin
- Access-Control-Request-Method
- Access-Control-Request-Headers
Requiring additional authentication for sensitive actions
Before performing critical and sensitive actions on your site, it is always a good idea to require your users to reauthenticate themselves. This could be a one-time password that gets sent to a registered email or phone number, a simple CAPTCHA, or revalidating passwords.
This prevents any sort of CSRF attacks and potentially even more dangerous attacks.
Conclusion
CSRF attacks amount to a large percentage of web-based attacks. Fortunately, it is easy to prevent and thwart attacks before they even happen. Ensure you’re following RESTful guidelines and stick to principles and policies designed to help you. Finally, set an AppSec performance monitoring lifecycle to ensure that code you write and deploy meets industry standards.
Practice coding securely and preventing vulnerabilities in our complimentary Security Labs Community Edition.